#include "./arrays.h"

void *mds_array1d_create( size_t n, size_t width )
{
	assert( width > 0 );
	assert( n > 0 );
#	if defined(NDEBUG)
	return     calloc( n, width );
#	else
	return mds_calloc( n, width );
#	endif
}

void mds_array1d_delete( void *a, size_t n, size_t width )
{
	assert( width > 0 );
	if( a )
	{
#	if defined(NDEBUG)
		free(a);
#	else
		mds_free(a, n, width );
#	endif
	}
}

void **mds_array2d_create( size_t r, size_t c, size_t width )
{
	assert( width > 0 );
	assert(r>0);
	assert(c>0);
	{
		void **rows = mds_array1d_create(r, sizeof(void*) );
		if( !rows )
			return NULL;
		else 
		{
			const size_t stride = c * width;
			char        *items  = mds_array1d_create(r*stride,1);
			if( !items )
			{
				mds_array1d_delete( rows, r, sizeof(void*) );
				return NULL;
			}
			else 
			{
				register size_t i;
				for( i=0; i < r; ++i, items += stride )
				{
					rows[i] = items;
				}
				return rows;
			}
			
		}
		
	}
	
}

void   mds_array2d_delete( void **p, size_t r, size_t c, size_t width )
{
	assert( width > 0 );
	if( p )
	{
		assert(r>0);
		assert(c>0);
		assert(p[0]!=NULL);
		mds_array1d_delete(p[0], r*c*width, 1);
		mds_array1d_delete(p,r,sizeof(void*));
	}
}


void ***mds_array3d_create( size_t r, size_t c, size_t d, size_t width )
{
	assert( width > 0 );
	assert( r>0 );
	assert( c>0 );
	assert( d>0 );
	{
		void ***rows = (void ***)mds_array2d_create(r,c,sizeof(void **));
		if( !rows ) 
			return NULL;
		else 
		{
			const size_t stride = d*width;
			char        *items  = mds_array1d_create(r*c*stride,1);
			if( !items )
			{
				mds_array2d_delete( (void *)rows, r, c, sizeof(void **) );
				return NULL;
			}
			else
			{
				register size_t i,j;
				for( i=0; i < r; ++i )
				{
					for( j=0; j < c; ++j, items += stride )
					{
						rows[i][j] = items;
					}
				}
				return rows;
			}
		}

	}
}

void mds_array3d_delete( void ***p, size_t r, size_t c , size_t d, size_t width )
{
	assert( width > 0 );
	if( p )
	{
		assert( r>0 );
		assert( c>0 );
		assert( d>0 );
		assert( p[0] );
		assert( p[0][0] );
		mds_array1d_delete( p[0][0], r*c*d*width,1);
		mds_array2d_delete( (void **)p, r, c, sizeof(void **));
	}
}

